package models

//权限相关
import (
	"errors"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"qysoft/libs/cache"
	"qysoft/libs/encrypt"
	"strings"
	"time"
)

//AccessTree 认证资源树数据结构
type AccessTree struct {
	Name     string       `json:"name"`
	Id       string       `json:"id"`
	Logo     string       `json:"logo"`
	Hiden    bool         `json:"hiden"`
	Children []AccessTree `json:"children"`
}

//GetAccessTreeByRoleId 根据角色获取该角色具有权限的资源树
func GetAccessTreeByRoleId(roleid string) *AccessTree {
	cid := "GetAccessTreeByRoleId.id." + roleid
	var tree AccessTree
	// tree := new(ResTree)
	err := cache.GetCache(cid, &tree)
	if err != nil {
		access := make([]orm.Params, 0)
		if roleid == "1" {
			_, access = GetAllResourceList(1)
		} else {
			access, _ = GetResourceByRoleId(roleid, 1)
		}
		pid := "0"
		getAccessTreeByRoleIdPid(access, roleid, pid, &tree)
		cache_expire, _ := beego.AppConfig.Int("cache_expire")
		cache.SetCache(cid, tree, cache_expire)
	}
	return &tree
}

//CheckLogin 录验证,用户名、密码，返回user和error
func CheckLogin(uname string, pwd string) (user *User, err error) {
	user, err = GetUserByUname(uname)
	if err != nil {
		return
	}
	beego.Debug(pwd)
	beego.Debug(encrypt.EncodeUserPwd(user.Salt, pwd))
	if encrypt.EncodeUserPwd(user.Salt, pwd) != user.Pwd {
		return nil, errors.New("密码不正确！")
	}
	return user, nil
}

//getAccessTreeByRoleIdPid
// 递归获取资源树，根据角色id、资源父id，AccessTree指针返回
func getAccessTreeByRoleIdPid(access []orm.Params, roleid, pid string, pTree *AccessTree) {
	i := -1
	for k, v := range access {
		dtree := AccessTree{
			v["Name"].(string),
			v["Id"].(string),
			v["Logo"].(string),
			v["Hiden"].(bool),
			nil}
		if v["Pid"].(string) == pid && i < k {
			i++
			pTree.Children = append(pTree.Children, dtree)
			getAccessTreeByRoleIdPid(access, roleid, v["Id"].(string), &pTree.Children[i])
		}
	}

}

//ResTree 资源树数据结构
type ResTree struct {
	Name     string    `json:"title"`
	Id       string    `json:"id"`
	Expand   bool      `json:"expand"`
	Checked  bool      `json:"checked"`
	Children []ResTree `json:"children"`
}

//ResTreeCheck 资源树数据结构
type ResTreeCheck struct {
	Name     string         `json:"title"`
	Id       string         `json:"id"`
	Checked  []string       `json:"checked"`
	Children []ResTreeCheck `json:"children"`
}

//GetResTreeByRoleId 根据角色获取所有资源分配情况的树
func GetResTreeByRoleId(roleid string) *ResTree {
	cid := "GetResTreeByRoleId.id." + roleid
	var tree ResTree
	// tree := new(ResTree)
	err := cache.GetCache(cid, &tree)
	if err != nil {
		pid := "0"
		// tree := new(ResTree)
		getResTreeByRoleIdPid(roleid, pid, &tree)
		cache_expire, _ := beego.AppConfig.Int("cache_expire")
		cache.SetCache(cid, tree, cache_expire)
	}

	return &tree
}

//GetAllResByRoleId 根据角色获取所有资源分配情况的树
func GetAllResByRoleId(roleid string) *ResTreeCheck {
	cid := "GetAllResByRoleId.id." + roleid
	var tree ResTreeCheck
	err := cache.GetCache(cid, &tree)
	if err != nil {
		pid := "0"
		getResTree(roleid, pid, &tree)
		tree.Checked, _ = GetResIdByRoleId(roleid)
		cache_expire, _ := beego.AppConfig.Int("cache_expire")
		cache.SetCache(cid, tree, cache_expire)
	}
	return &tree
}

//getResTreeByRoleIdPid 递归获取目录资源树，根据角色id、资源父id，ResTree指针返回
func getResTreeByRoleIdPid(roleid string, pid string, pTree *ResTree) {
	reslist, _ := GetResSubTree(pid, 1)
	if len(reslist) < 1 {
		return
	}
	for k, v := range reslist {
		dtree := ResTree{
			v["Name"].(string),
			v["Id"].(string),
			true,
			GetRoleOwnerResource(roleid, v["Id"].(string)),
			nil}
		if v["Pid"].(string) == "0" && v["Type"].(int64) == 1 {
			dtree = ResTree{
				v["Name"].(string),
				v["Id"].(string),
				true,
				false,
				nil}
		}
		pTree.Children = append(pTree.Children, dtree)
		getResTreeByRoleIdPid(roleid, v["Id"].(string), &pTree.Children[k])
	}

}

//getResTree 递归获取资源树，根据角色id、资源父id，ResTree指针返回
func getResTree(roleid string, pid string, pTree *ResTreeCheck) {
	reslist, _ := GetResSubTree(pid, 1)
	if len(reslist) < 1 {
		return
	}
	for k, v := range reslist {
		dtree := ResTreeCheck{
			v["Name"].(string),
			v["Id"].(string),
			nil,
			nil}
		if v["Pid"].(string) == "0" {
			dtree = ResTreeCheck{
				v["Name"].(string),
				v["Id"].(string),
				nil,
				nil}
		}
		pTree.Children = append(pTree.Children, dtree)
		getResTree(roleid, v["Id"].(string), &pTree.Children[k])
	}

}

//SoftDelete 软删除表 一般用作事务处理
//Param o orm.Ormer
//Param objname string 表名
//Param query map[string]string 筛选条件
//Param uname string 操作者名称
//return num, error 软删除条数
func SoftDelete(o orm.Ormer, objname string, query map[string]interface{}, uname string) (num int64, err error) {
	qs := o.QueryTable(objname)
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	num, err = qs.Update(orm.Params{
		"isDelete": 1,
		"updater":  uname,
		"Utime":    time.Now(),
	})
	return

}

//SoftDeleteObject 软删除表 普通调用
func SoftDeleteObject(objname string, query map[string]interface{}, uname string) (err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(objname)
	for k, v := range query {
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	_, err = qs.Update(orm.Params{
		"isDelete": 1,
		"updater":  uname,
		"Utime":    time.Now(),
	})
	return

}
